﻿package  webCode {
	import flash.display.Sprite;
	import flash.display.DisplayObject;
	import flash.events.*;
	import flash.utils.Timer;
	import webCode.MainApp;
	import flash.display.Stage;
	
	public class Web extends Sprite{

		//Attributes
		var nodes:Array;
		var color:uint;
		var thickness:Number;
		var sides:Number;
		var center:webNode;
		var theta:Number;
		var rads:Number;
		var radius:Number;
		var rings:Number; //number of rings of nodes around the center point
		var springs:Array;
		var v:Number;
		var webTimer:Timer;
		var centerDrawn:Boolean;
		var redNode:webNode;             //the redNode is the one that is going to turn red and be dragged.
		var minDistance:Number= 65;			//the minimum distance is the lowest distance you can drag the node for it to change
		var score:Number;             //the player's score
		var setX:Number;               //setX and setY are the X and Y the redNode was at before it was being dragged
		var setY:Number;
		//var checkingDistance:Boolean;      //whether or not the distance is being checked(whether the redNode is being dragged)
		var redNodeIndex:int;
		var bfsQueue:Array;
		var storedSWidth:Number;
		var storedSHeight:Number;
		var myBox:Box;
		
		//displayLayers
		public var nodeLayer:Sprite = new Sprite();
		public var springLayer:Sprite = new Sprite();
	
		public function Web(cenX:Number, cenY:Number, numRings:Number, radius:Number, givenSides:Number, givenSWidth:Number, givenSHeight:Number, thickness:Number =1, color:uint=0x40FF00) {
			x=0;
			y=0;
			this.thickness=thickness;
			nodes = new Array();
			springs = new Array();
			this.color = color;
			this.radius = radius;
			centerDrawn = false;
			sides = givenSides;
			bfsQueue = new Array();
			rings= numRings;
			storedSWidth=givenSWidth;
			storedSHeight=givenSHeight;
			init(cenX, cenY);
			myBox = new Box(storedSWidth, storedSHeight);
			myBox.Randomize();
			addChild(myBox);
			addChild(springLayer);
			addChild(nodeLayer);
		}
		
		public function init(i:Number, j:Number):void
		{
			center = new webNode();
			score = 0;
			setTimer();
			center.x=i;
			center.y=j;
			nodes.push(center);
			nodeLayer.addChild(center);
			v=1;                                          //v is how we keep track of which nodes and strings we are drawing
			makeNodes(rings);
			setStaticNodes();
			setDrags();
			addVSprings();
			drawSprings();
			resetRedNode();                               //redNode is a random number from 0 to any vertex that is movable
			drawNodes();
		}
		
		public function update(e:Event):void
		{
			
			bfsQueue.push(nodes[0]);
			while(bfsQueue.length>0)
			{
				var tempNode:webNode = bfsQueue.shift();
				tempNode.updateConnections();
				for each(var childNode:webNode in tempNode.childrenNodes)
				{
					bfsQueue.push(childNode);
				}
			}
			
			if (redNode != null && redNode.hitTestObject(myBox))
			{
				myBox.Randomize();
				trace("myBox randomized");
				onrelease(new MouseEvent("s;alksdfj"));
				resetRedNode();
				drawNodes();
			}
			drawSprings();
		}
		
		public function setTimer():void {
			webTimer = new Timer(25,0);
			webTimer.addEventListener(TimerEvent.TIMER, update);
			webTimer.start();
			
		}
		
		//////////////////////////////////////////////////////////////////////
		//turns the red node green and turns a different node into the red node.
		/////////////////////////////////////////////////////////////
		public function resetRedNode()
		{
			if (redNode != null)
			{
				redNode.setToGreen();
			}
			redNodeIndex = Math.floor(Math.random() * (nodes.length-sides));    
			redNode = nodes[redNodeIndex];
			redNode.setToRed();
		}
		
		/////////////////////////////////////////////////
		//Recursively adds nodes to the list of nodes in the web in their correct position (starting in the center)
		//Also calles addHSprings while nodes are being added to put springs between them
		////////////////////////////////////////////////////
		public function makeNodes(n:Number):void
		{
			if (n >0)
			{
				for(var x:Number = 1; x<= sides; x++)
				{
					theta= x * (360/sides);
					makeNode(rads= theta * Math.PI / 180);
					addHSprings(x);
					v++;
				}
				radius += 60;
				makeNodes(n-1);
			}
		}
		
		////////////////////////////////////////////////////////////////////////////////////
		//goes through the nodes and makes the last ring of them a boolean of not movable
		//////////////////////////////////////////////////////////////////////////////////////
		public function setStaticNodes():void
		{
			for (var x:Number = nodes.length-1; x>= nodes.length-sides; x--)
			{
				nodes[x].setStatic(false);
			}
		}
		
		/////////////////////////////////////////////////////////////////////
		//sets up event listeners for the movable nodes
		/////////////////////////////////////////////////////////////////////////////////
		public function setDrags():void
		{
			for each (var n:webNode in nodes)
			{
				if (n.canMove)
				{
					n.addEventListener(MouseEvent.MOUSE_DOWN, onpress);
				}
			}
		}
		
		//////////////////////////////////////////////////////////////////////
		//if a node is being dragged, calls the startDrag();
		////////////////////////////////////////////////////////////////
		public function onpress(e:MouseEvent):void
		{
			e.target.startDrag();
			e.target.beingDragged=true;
		}
		
		/////////////////////////////////////////////////////////////////
		//releases all the nodes from dragging
		//////////////////////////////////////////////////////////
		public function onrelease(e:MouseEvent):void
		{
			for each(var n:webNode in nodes)
			{
				n.stopDrag();
				n.beingDragged=false;
			}
		}
		
		//////////////////////////////////////////////////////
		//Makes a new spring depending on which iteration around the web we're on
		/////////////////////////////////////////////////////////////
		public function addHSprings(x:Number)
		{
			if (x>1 && x<=sides)
			{
				springs.push(new Spring(nodes[v], nodes[v-1]));
				springs.push(new Spring(nodes[v-1], nodes[v]));
				springLayer.addChild(springs[springs.length-1]);
				//springLayer.addChild(springs[springs.length-2]);
			}
			if (x==sides)
			{
				springs.push(new Spring(nodes[v-sides+1], nodes[v]));
				springs.push(new Spring(nodes[v], nodes[v-sides+1]));
				springLayer.addChild(springs[springs.length-1]);
				//springLayer.addChild(springs[springs.length-2]);
			}
		}
		
		///////////////////////////////////////////////////////////////////
		//Goes through the list of vertices and adds springs between every 2 that should be connected.
		//////////////////////////////////////////////////////////////////////////////////////////
		public function addVSprings()
		{
			for(var x:Number = 1; x <=sides; x++)
			{
				springs.push(new Spring(nodes[0], nodes[x]));
				springs.push(new Spring(nodes[x], nodes[0]));
				nodes[0].childrenNodes.push(nodes[x]);
				springLayer.addChild(springs[springs.length-1]);
				//springLayer.addChild(springs[springs.length-2]);

			}
			for(var y:Number = sides+1; y < nodes.length; y++)
			{
				springs.push(new Spring(nodes[y], nodes[y-sides]));
				springs.push(new Spring(nodes[y-sides], nodes[y]));
				nodes[y-1].childrenNodes.push(nodes[y]);
				springLayer.addChild(springs[springs.length-1]);
				//springLayer.addChild(springs[springs.length-2]);
			}
		}
		
		/////////////////////////////////////////////////////////////////
		//Adds a new webNode onto nodes with the rotation of rads from the previous node
		////////////////////////////////////////////////////////////////////////
		public function makeNode(rads:Number)
		{
			var tempNode:webNode = new webNode();
			tempNode.x = center.x+radius*Math.cos(rads);
			tempNode.y = center.y+radius*Math.sin(rads);
			nodes.push(tempNode);
			nodeLayer.addChild(nodes[nodes.length-1]);
		}
		
		
		
		//////////////////////////////////////////////////
		//Goes through the list of Nodes and draws a circle at each one
		////////////////////////////////////////////////////
		public function drawNodes():void
		{
			for (var i:Number = 0; i<nodes.length; i++)
			{
				if (i == redNodeIndex)
					nodes[i].setToRed();
					
				nodes[i].render();
			}
		}
		
		public function drawSprings():void
		{
			for each(var s:Spring in springs)
			{
				s.drawSpring();
			}
		}

	}
	
}
